﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionTree.Interface
{
    /// <summary>
    /// 表达式解析抽象类
    /// </summary>
    public abstract class BaseExpresstionHandler
    {
        protected ExpressionHandler handler = null;
        public void SetExpressionHandler(ExpressionHandler handler)
        {
            this.handler = handler;
        }
        /// <summary>
        /// 二元运算
        /// </summary>
        /// <param name="expression"></param>
        public  virtual string BinaryExpressionHandler(Expression expression)
        {
            var exp = expression as BinaryExpression;
            var builder = new StringBuilder();
            builder.Append("(");
            var left = exp.Left;
            builder.Append(handler.Handler(left));

            var nodeType = exp.NodeType;
            builder.AppendFormat(" {0} ", OperateSymbol.Name2Symbol(nodeType.ToString()));
            var right = exp.Right;
            builder.Append(handler.Handler(right));
            builder.Append(")");
            return builder.ToString();
        }
        /// <summary>
        /// 常量
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual string ConstantExpressionHandler(Expression expression)
        {
            var exp = expression as ConstantExpression;
            var value = exp.Value;
            if (exp.Type.Name.ToLower().StartsWith("int"))
                return value.ToString();
            else
                return string.Format("'{0}'", value.ToString());
        }
        /// <summary>
        /// 成员（类似属性）
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual string MemberExpressionHandler(Expression expression)
        {
            var exp = expression as MemberExpression;
            var memberInfo = exp.Member;
            return memberInfo.Name;
        }

        /// <summary>
        /// 方法
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual string MethodCallExpressionHandler(Expression expression)
        {
            var exp = expression as MethodCallExpression;
            var builder = new StringBuilder();
            var obj = exp.Object;
            //builder.Append("(");
            //builder.Append(routing.Handler(obj));
            //var method = exp.Method;
            //builder.AppendFormat(" {0} ", method.Name);
            //var strList = new List<string>();
            //foreach (var Argument in exp.Arguments)
            //{
            //    strList.Add(routing.Handler(Argument));
            //}
            //builder.AppendFormat("'{0}'", string.Join(",", strList.ToArray()));
            //builder.Append(")");

            builder.Append("(");
            var fieldName = handler.Handler(obj);
            var method = exp.Method;
            var strList = new List<string>();
            foreach (var Argument in exp.Arguments)
            {
                strList.Add(handler.Handler(Argument));
            }
            builder.Append(OperateSymbol.Method2Symbol(fieldName, method.Name, strList.ToArray()));
            builder.Append(")");
            return builder.ToString();
        }
        /// <summary>
        /// 新对象
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual string NewExpressionHandler(Expression expression)
        {
            var exp = expression as NewExpression;
            var strList = new List<string>();
            foreach (var Argument in exp.Arguments)
            {
                strList.Add(handler.Handler(Argument));
            }
            return string.Join(",", strList.ToArray());
        }
        /// <summary>
        /// lambda
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual string LambdaExpressionHandler(Expression expression)
        {
            var exp = expression as LambdaExpression;
            return handler.Handler(exp.Body);
        }
    }
}
